package cn.tworice.blog.web;

import cn.tworice.blog.entity.Dir;
import cn.tworice.blog.utils.CoreService;
import cn.tworice.blog.service.FileService;
import cn.tworice.blog.utils.FdfsUtil;
import com.lmk.core.web.support.api.RequestResult;
import com.lmk.core.web.support.api.StatusCode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequestMapping("/api/file")
@CrossOrigin
@Api(tags = "文件系统接口")
public class FileController {

    // 文件访问路径
    @Value("${upload.url}")
    String url;

    @Autowired
    private FileService fileService;

    @Autowired
    private FdfsUtil fdfsUtil;




    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("list")
    @ApiOperation("根据目录ID获取目录信息")
    public RequestResult list(@ApiParam("目录ID") Integer dir){

        RequestResult result=fileService.queryListByDirId(dir); // 查询当前文件夹下的文件夹列表和文件列表
        Dir currentDir=fileService.queryDirByDirId(dir); // 获取当前文件夹信息
        String url=this.url;
        result.appendData("path",url); // 文件访问的地址
        result.appendData("currentDir",currentDir);// 上级文件夹名称
        log.info("获取目录ID-"+dir+"信息，访问位置："+url);
        return result;
    }

    @PostMapping("upload")
    @ApiOperation("普通文件上传")
    public RequestResult upload(@RequestParam(required = false,value = "file")@ApiParam("MultipartFile文件") MultipartFile file,@RequestParam(required = false,value = "dir")@ApiParam("目录ID") Integer dir){
        log.info("文件上传目录ID-"+dir);
        RequestResult result=new RequestResult();
//        try {
//            // 通过文件夹名字创建文件
//            String fileName="/"+fileService.queryDirByDirId(dir).getDirName()+"/";// 文件夹名称
////            String realPath = req.getServletContext().getRealPath("/upload") + format;
////            String realPath=path+fileName;
//            File folder = new File(realPath);
//            System.out.println("文件路径"+realPath);
//
//            if (!folder.exists()) {
//                log.info("创建目录-"+realPath);
//                folder.mkdirs();
//            }
//            // 文件原名字
//            String oldName = file.getOriginalFilename();
//
//            // 新名字
//            String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
//            file.transferTo(new File(folder,newName));
//
//            // 用户访问路径 不含文件名
////            String url = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/upload" + fileName + newName;
//            String url=this.url+fileName;
//
//            // 时间
//            long date=new Date().getTime();
//            log.info("文件上传写入数据库-"+oldName+","+newName+","+dir+","+date);
//            // 写入数据库
//            int i=fileService.insertFile(new cn.tworice.blog.entity.File(oldName,newName,0,dir,date));
//            System.out.println(i);
//            // 判断写入状态
//            if(i==-1){
//                log.warn("文件上传失败，，文件名称已经存在！");
//                result.setCode(new StatusCode(413,"文件上传失败，当前目录中文件已经存在！"));
//            }else if(i==1){
//                log.info("文件上传成功，位置："+url);
//                result.setCode(new StatusCode(200,"文件上传成功"));
//                result.appendData("path",url);
//            }else{
//                log.error("文件上传错误，上传位置："+url);
//                result.setCode(new StatusCode(413,"文件上传失败"));
//            }
//
//        } catch (IOException e) {
//            e.printStackTrace();
//            result.setCode(new StatusCode(501,"文件上传失败"));
//            log.error("文件上传失败，IOException未知问题");
//        }
        return result;
    }

    @PostMapping("fdfsUpload")
    @ApiOperation("FastDFS文件上传接口")
    public RequestResult fdfsUpload(@ApiParam("文件字节流") @RequestParam MultipartFile file,@RequestParam(required = false,value = "dir")@ApiParam("目录ID") Integer dir) throws IOException {
        RequestResult result = new RequestResult();

        try{

            // 文件原名字
            String oldName = file.getOriginalFilename();

            // 文件新名字
            String newName = fdfsUtil.uploadFile(file);

            // 时间
            long date=new Date().getTime();

            // 访问路径
            String url=this.url+newName;

            // 写入数据库
            int i=fileService.insertFile(new cn.tworice.blog.entity.File(oldName,newName,0,dir,date));
            if(i==-1){
                log.warn("文件上传失败，，文件名称已经存在！");
                result.setCode(new StatusCode(413,"文件上传失败，当前目录中文件已经存在！"));
            }else if(i==1){
                log.info("FastDFS文件上传写入数据库-"+oldName+","+newName+","+dir+","+date);
                log.info("文件上传成功，位置："+url);
                result.setCode(new StatusCode(200,"文件上传成功"));
                result.appendData("path",url);
            }else{
                log.error("文件上传错误，上传位置："+url);
                result.setCode(new StatusCode(413,"文件上传失败"));
            }

        }catch (Exception ex){
            result.setCode(new StatusCode(501,"文件上传失败，请检查文件的合法性！"));
            log.error("文件上传失败，IOException未知问题");
        }

        return result;
    }

    @DeleteMapping("delFile")
    @ApiOperation("删除文件")
    public RequestResult delFile(@ApiParam("文件ID") Integer id){
        RequestResult result=new RequestResult();

        // 获取该文件信息
        cn.tworice.blog.entity.File file=fileService.queryFileById(id);
        log.info("请求删除文件-"+file.getDirName()+"/"+file.getOldName()+",存储位置为-"+file.getNewName());
        // 删除文件
        try {
            fdfsUtil.delFile(file.getNewName());
            fileService.delFileById(id);
            result.setCode(new StatusCode(200,"删除文件成功！"));
        }catch (Exception ex){
            result.setCode(new StatusCode(203,"删除文件失败！"));
            log.info("删除文件ID"+file.getId()+"失败-"+ex.getMessage());
        }
        return result;
    }

    /**
     * 打开保险箱，参数是保险箱密码，有默认值
     * @author 二饭
     * @email 1786705138@qq.com
     */
    @PostMapping("openSafe")
    @ApiOperation("打开保险箱")
    public RequestResult openSafe(@RequestParam(value = "pwd",required = false,defaultValue = "null") @ApiParam("保险箱密码") String pwd,@ApiParam("Request") HttpServletRequest request){
        // 获取当前IP地址
        String ip=CoreService.getIpAddress(request);
        log.info("IP-"+ip+"-请求打开保险箱，密码为-"+pwd);
        RequestResult result=fileService.checkSafePwd(pwd);
        if(result.getCode().getCode()==200){
            redisTemplate.opsForValue().set(ip,"true",5,TimeUnit.MINUTES);
        }
        return result;
    }

    /**
     * 通过IP地址判断是否已经输入过密码
     * @author 二饭
     * @email 1786705138@qq.com
     */
    @GetMapping("checkSafe")
    @ApiOperation("判断是否需要输入密码打开保险箱")
    public RequestResult checkSafe(HttpServletRequest request){
        // 获取当前IP地址
        String ip=CoreService.getIpAddress(request);

        RequestResult result=new RequestResult();
        // 查询当前IP是否需要输入密码
        String ret=(String) redisTemplate.opsForValue().get(ip);
        if (ret==null || ret.equals("null")){
            result.setCode(new StatusCode(203,"保险箱内容未获得授权！"));
        }else {
            result.setCode(new StatusCode(200,"已打开保险箱！"));
            result.appendData("safeFiles",fileService.getSafeFile());
            redisTemplate.opsForValue().set(ip,"true",5,TimeUnit.MINUTES);
        }
        return result;
    }

    @GetMapping("addSafe/{id}")
    @ApiOperation("将文件放入保险箱")
    public RequestResult addSafe(@ApiParam("文件ID") @PathVariable("id") Integer id){
        return fileService.addSafe(id);
    }

    @GetMapping("removeSafe/{id}")
    @ApiOperation("将文件移出保险箱")
    public RequestResult removeSafe(@ApiParam("文件ID") @PathVariable("id") Integer id){
        return fileService.removeSafe(id);
    }
}
